﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

namespace HzySocket.WebSocket.Core
{
    using HzySocket.WebSocket.Interface;
    using Microsoft.AspNetCore.Http;
    using Newtonsoft.Json;
    using System.Net.WebSockets;
    using System.Threading;
    using System.Threading.Tasks;

    public class WebSocketSessionBase : IWebSocketSessionBase
    {
        /// <summary>
        /// 上下文连接 Id
        /// context.Connection.Id
        /// </summary>
        public virtual string SessionKey { get; set; }

        /// <summary>
        /// httpContext 上下文
        /// </summary>
        public virtual HttpContext HttpContext { get; set; }

        /// <summary>
        /// webSocket 对象
        /// </summary>
        public virtual WebSocket WebSocket { get; set; }

        /// <summary>
        /// 开始时间
        /// </summary>
        public virtual DateTime StartTime { get; set; }

        /// <summary>
        /// 最后更新时间
        /// </summary>
        public virtual DateTime LastActiveTime { get; set; }

        /// <summary>
        /// 
        /// </summary>
        public virtual CancellationToken GetCancellationToken { get; set; } = CancellationToken.None;

        /// <summary>
        /// 发送异常回调事件
        /// </summary>
        public virtual Action<Exception> SendExceptionCall { get; set; }

        /// <summary>
        /// 接收到的 数据信息
        /// </summary>
        public virtual StringBuilder Data { get; set; }

        /// <summary>
        /// 发送消息 将会把信息转换为 Json 发送给客户端
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="data"></param>
        /// <returns></returns>
        public virtual async Task SendAsync<T>(T data)
            => await this.SendAsync(SerializeToJson(data));

        /// <summary>
        /// 发送一段普通的文本
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public virtual async Task SendAsync(string data)
        {
            try
            {
                if (string.IsNullOrWhiteSpace(data)) return;
                
                // 检查WebSocket状态
                if (this.WebSocket == null || this.WebSocket.State != WebSocketState.Open)
                {
                    Console.WriteLine($"WebSocket is not open. Current state: {this.WebSocket?.State}");
                    return;
                }
                
                var segment = new ArraySegment<byte>(Encoding.UTF8.GetBytes(data));
                await this.WebSocket.SendAsync(segment, WebSocketMessageType.Text, true, GetCancellationToken);
            }
            catch (TaskCanceledException ex)
            {
                // 发送操作被取消，记录日志但不抛出异常
                SendExceptionCall?.Invoke(ex);
            }
            catch (WebSocketException ex)
            {
                // WebSocket异常，可能是连接已断开
                SendExceptionCall?.Invoke(ex);
            }
            catch (ObjectDisposedException ex)
            {
                // WebSocket已被释放
                SendExceptionCall?.Invoke(ex);
            }
            catch (Exception ex)
            {
                // 其他异常
                Console.WriteLine($"Error sending message: {ex}");
                SendExceptionCall?.Invoke(ex);
                
                // 根据需要决定是否重新抛出异常
                // throw;
            }
        }

        private static readonly JsonSerializer JsonSerializer = new JsonSerializer();
        
        /// <summary>
        /// 使用静态JsonSerializer序列化对象以减少内存分配
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="data"></param>
        /// <returns></returns>
        private static string SerializeToJson<T>(T data)
        {
            using (var stringWriter = new StringWriter())
            {
                using (var jsonWriter = new JsonTextWriter(stringWriter))
                {
                    JsonSerializer.Serialize(jsonWriter, data);
                    return stringWriter.ToString();
                }
            }
        }
    }
}